﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CastleOfTheDisillusioned.Location.Maps {
	class Cell : BoundingBox {

		private double _x = 0;
		public override double X {
			get {
				return _x;
			}
			set {
				double xdif = value - _x;

				_x += xdif;
				foreach (Tile t in Tiles) {
					t.X += xdif;
				}

				foreach (Enemy e in Enemies) {
					e.X += xdif;
				}

				foreach (Entity e in Entities) {
					e.X += xdif;
				}
			}
		}

		private double _y = 0;
		public override double Y {
			get {
				return _y;
			}
			set {
				double ydif = value - _y;

				_y += ydif;
				foreach (Tile t in Tiles) {
					t.Y += ydif;
				}

				foreach (Enemy e in Enemies) {
					e.Y += ydif;
				}

				foreach (Entity e in Entities) {
					e.Y += ydif;
				}
			}
		}


		public const int CellHeight = 15;
		public const int CellWidth = 20;

		public List<Tile> Tiles = new List<Tile>();
		public List<Enemy> Enemies = new List<Enemy>();
		public List<Entity> Entities = new List<Entity>();

		public List<Node> Nodes = new List<Node>();

		public virtual void Update() {
			for (int i = 0; i < Enemies.Count; i++) {
				Enemy e = Enemies[i];
				if (e.IsDead) {
					Enemies.Remove(e);
					i--;
				} else {
					e.Update();
				}
			}

			foreach (Entity e in Entities) {
				e.Update();
			}
		}

		protected void AddTile(double x, double y) {
			Tiles.Add(new Tile(x, y));
		}

		protected void AddTile(Tile t) {
			Tiles.Add(t);
		}

		protected void AddEnemy(Enemy enemy) {
			Enemies.Add(enemy);
		}

		protected void AddEntity(Entity entity) {
			Entities.Add(entity);
		}

		#region---Map Utilities---
		protected void RemoveTiles(double X, double Y, double Width, double Height) {
			BoundingBox area = new BoundingBox(X, Y, Width, Height);

			for (int i = 0; i < Tiles.Count; i++) {
				Tile t = Tiles[i];
				if (t.CollidesWith(area)) {
					Tiles.Remove(t);
					i--;
				}
			}
		}

		protected void AddTileRow(double XStart, double YStart, int Count) {
			for (int i = 0; i < Count; i++) {
				this.AddTile(XStart + i, YStart);
			}
		}

		protected void AddTileColumn(double XStart, double YStart, int Count) {
			for (int i = 0; i < Count; i++) {
				this.AddTile(XStart, YStart + i);
			}
		}

		protected void AddTileOutline(double X, double Y, int WCount, int HCount) {
			AddTileRow(X, Y, WCount);
			AddTileRow(X, Y + HCount - 1, WCount);
			AddTileColumn(X, Y + 1, HCount - 2);
			AddTileColumn(X + WCount - 1, Y + 1, HCount - 2);
		}

		protected void AddNode(Node node) {
			this.RemoveTiles(node.X - 1, node.Y - 1, 3, 3);
			this.Nodes.Add(node);
		}

		protected void AddLeftNode(double X, double Y) {
			this.RemoveTiles(X - 1, Y - 1, 3, 3);
			this.Nodes.Add(new Node(X, Y, this, Direction.Left));
		}

		protected void AddRightNode(double X, double Y) {
			this.RemoveTiles(X - 1, Y - 1, 3, 3);
			this.Nodes.Add(new Node(X, Y, this, Direction.Right));
		}

		public List<Node> GetFreeNodes() {
			List<Node> FreeNodes = new List<Node>();
			foreach (Node n in Nodes) {
				if (!n.Taken) {
					FreeNodes.Add(n);
				}
			}
			return Utilities.Shuffle(FreeNodes);
		}
		
		public List<Node> GetFreeNodes(Direction ConnectionType) {
			List<Node> FreeNodes = new List<Node>();
			foreach (Node n in Nodes) {
				if (!n.Taken && n.ConnectionType == ConnectionType) {
					FreeNodes.Add(n);
				}
			}
			return Utilities.Shuffle(FreeNodes);
		}

		//protected void AddLeftPortal(double X, double Y, Type Map) {
		//    this.RemoveTiles(X, Y + 0.1, 1, 2.8);
		//    this.AddEntity(new Portal(X - 1.5, Y, 2, 3, Map));
		//}

		//protected void AddRightPortal(double X, double Y, Type Map) {
		//    this.RemoveTiles(X, Y + 0.1, 1, 2.8);
		//    this.AddEntity(new Portal(X + 0.5, Y, 2, 3, Map));
		//}
		#endregion
	}
}
